package cn.legym.garp.gateway.traffic.config;

import cn.legym.garp.gateway.traffic.dynamic.DynamicResourceManager;
import cn.legym.garp.gateway.traffic.dynamic.SentinelDatasourceWatcher;
import cn.legym.garp.gateway.traffic.dynamic.bean.DynamicResourceDefinition;
import cn.legym.garp.gateway.traffic.dynamic.watcher.InMemoryDatasourceWatcher;
import cn.legym.garp.gateway.traffic.dynamic.watcher.NacosDatasourceWatcher;
import cn.legym.garp.gateway.traffic.rule.TrafficRule;
import cn.legym.garp.gateway.traffic.rule.TrafficRuleManager;
import com.alibaba.cloud.sentinel.SentinelProperties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * create by pipisun on 2021/9/9
 * copyright © 2017-2021 Legym Technology Co.,Ltd. All rights reserve
 * d.
 * file description:
 * <p>
 * 从配置中查找并加载自定义限流规则相关内容。
 * <p>
 * 自定义规则分为： 请求转义规则{@link TrafficRule} 和 自定义资源{@link DynamicResourceDefinition}
 * <p>
 * last update by {} on {}
 * update description:
 */
@Data
@Configuration
//@ConfigurationProperties(prefix = "spring.cloud.sentinel.dynamic", name = "enabled", havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(NacosDataSourceConfig.class)
@ConfigurationProperties("spring.cloud.sentinel.dynamic")
@AutoConfigureAfter(SentinelProperties.class)
@Slf4j
public class TrafficConfig {

    private boolean enabled;

    private SentinelDatasourceStrategy sentinelDatasourceStrategy = SentinelDatasourceStrategy.memory;

    @Autowired
    private NacosDataSourceConfig nacosConfig;


    @Bean
    public SentinelDatasourceWatcher sentinelDatasourceWatcher() {
        try {
            return sentinelDatasourceStrategy.getWatcherClazz().newInstance();
        } catch (Exception e) {
            log.error("", e);
        }
        throw new IllegalStateException("sentinel datasource strategy is NULL");
    }

    /**
     * 自定义动态限流配置 加载+监听
     * spring.cloud.sentinel.dynamic.datasource.*.rule -> {@link TrafficRule}
     * spring.cloud.sentinel.dynamic.datasource.*.resource -> {@link DynamicResourceDefinition}
     */
    public enum DataSourceType {
        /**
         * 自定义请求转义规则
         */
        rule(TrafficRule.class, TrafficRuleManager.class),
        /**
         * 自定义动态限流规则
         */
        resource(DynamicResourceDefinition.class, DynamicResourceManager.class),
        ;

        private final Class<?> dataClazz;
        private final Class<? extends TrafficDataSourceListener<?>> listenerClazz;

        DataSourceType(Class<?> dataClazz, Class<? extends TrafficDataSourceListener<?>> listenerClazz) {
            this.dataClazz = dataClazz;
            this.listenerClazz = listenerClazz;
        }

        public Class<? extends TrafficDataSourceListener<?>> listenerClazz() {
            return listenerClazz;
        }

        public Class<?> getDataClazz() {
            return dataClazz;
        }
    }

    public enum SentinelDatasourceStrategy {
        memory(InMemoryDatasourceWatcher.class),
        nacos(NacosDatasourceWatcher.class),
        ;

        private final Class<? extends SentinelDatasourceWatcher> watcherClazz;

        SentinelDatasourceStrategy(Class<? extends SentinelDatasourceWatcher> watcherClazz) {
            this.watcherClazz = watcherClazz;
        }

        public Class<? extends SentinelDatasourceWatcher> getWatcherClazz() {
            return watcherClazz;
        }
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}
